{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e8cfec04",
   "metadata": {},
   "source": [
    "# Demonstrative Examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "99b34125",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afae3bde",
   "metadata": {},
   "source": [
    "## 1. Load sample dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0d2960e2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "shape of alarm data: (30691, 4)\n",
      "shape of true graph: (59, 59)\n",
      "shape of causal prior matrix: (59, 59)\n"
     ]
    }
   ],
   "source": [
    "# alarm data\n",
    "alarms = pd.read_csv(r'./sample/alarm.csv')\n",
    "# causal_prior\n",
    "causal_prior= np.load(r'./sample/causal_prior.npy')\n",
    "# ground_truths, this file will not be provided in the submission stage\n",
    "true_graph = np.load(r'./sample/true_graph.npy')\n",
    "\n",
    "print(f\"shape of alarm data: {alarms.shape}\")\n",
    "print(f\"shape of true graph: {true_graph.shape}\")\n",
    "print(f\"shape of causal prior matrix: {causal_prior.shape}\")\n",
    "\n",
    "# Notes: topology.npy and rca_prior.csv are not used in this demo code."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43ade713",
   "metadata": {},
   "source": [
    "## 2.  Select the gCastle as the base algorithm library"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "102fd26b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from castle.algorithms import Notears,PC\n",
    "from castle.common.plot_dag import GraphDAG\n",
    "from castle.metrics import MetricsDAG\n",
    "from castle.common.priori_knowledge import PrioriKnowledge"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef8993ad",
   "metadata": {},
   "source": [
    "## 3. Case Studies"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dee8f9bc",
   "metadata": {},
   "source": [
    "### 3.1 Setting 1:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21044716",
   "metadata": {},
   "source": [
    "  1. Data files: \"alarm.csv\".\n",
    "  2. Use a time sliding window to generate IID samples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0b2a4700",
   "metadata": {},
   "outputs": [],
   "source": [
    "TIME_WIN_SIZE  = 300"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ec79d80e",
   "metadata": {},
   "outputs": [],
   "source": [
    "alarms = alarms.sort_values(by='start_timestamp')\n",
    "alarms['win_id'] = alarms['start_timestamp'].map(lambda elem:int(elem/TIME_WIN_SIZE))\n",
    "\n",
    "samples=alarms.groupby(['alarm_id','win_id'])['start_timestamp'].count().unstack('alarm_id')\n",
    "samples = samples.dropna(how='all').fillna(0)\n",
    "samples = samples.sort_index(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "08ca1ef4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>alarm_id</th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "      <th>6</th>\n",
       "      <th>7</th>\n",
       "      <th>8</th>\n",
       "      <th>9</th>\n",
       "      <th>...</th>\n",
       "      <th>49</th>\n",
       "      <th>50</th>\n",
       "      <th>51</th>\n",
       "      <th>52</th>\n",
       "      <th>53</th>\n",
       "      <th>54</th>\n",
       "      <th>55</th>\n",
       "      <th>56</th>\n",
       "      <th>57</th>\n",
       "      <th>58</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>win_id</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3 rows × 59 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "alarm_id   0    1    2    3    4    5    6    7    8    9   ...   49   50  \\\n",
       "win_id                                                      ...             \n",
       "0         0.0  0.0  0.0  0.0  0.0  0.0  1.0  1.0  0.0  0.0  ...  0.0  0.0   \n",
       "1         0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  ...  0.0  1.0   \n",
       "2         1.0  0.0  0.0  0.0  0.0  0.0  1.0  1.0  1.0  0.0  ...  0.0  1.0   \n",
       "\n",
       "alarm_id   51   52   53   54   55   56   57   58  \n",
       "win_id                                            \n",
       "0         0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0  \n",
       "1         0.0  0.0  1.0  0.0  1.0  0.0  0.0  0.0  \n",
       "2         0.0  0.0  0.0  3.0  0.0  3.0  1.0  0.0  \n",
       "\n",
       "[3 rows x 59 columns]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "samples.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2cba03a8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1981, 59)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "samples.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e7c7df9",
   "metadata": {},
   "source": [
    "####  Exemplified by the NOTEARS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "24dd01ae",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-08-08 20:26:27,975 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:195] - INFO: [start]: n=1981, d=59, iter_=100, h_=1e-08, rho_=1e+16\n",
      "2023-08-08 20:26:28,224 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 0] h=1.433e-01, loss=15.762, rho=1.0e+00\n",
      "2023-08-08 20:26:28,327 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 1] h=1.295e-01, loss=11.476, rho=1.0e+00\n",
      "2023-08-08 20:26:28,460 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 1] h=8.740e-02, loss=11.568, rho=1.0e+01\n",
      "2023-08-08 20:26:28,625 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 1] h=4.041e-02, loss=12.493, rho=1.0e+02\n",
      "2023-08-08 20:26:28,880 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 1] h=1.273e-02, loss=21.739, rho=1.0e+03\n",
      "2023-08-08 20:26:29,105 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 2] h=7.282e-03, loss=12.024, rho=1.0e+03\n",
      "2023-08-08 20:26:29,504 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 2] h=2.782e-03, loss=12.753, rho=1.0e+04\n",
      "2023-08-08 20:26:29,729 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 3] h=1.721e-03, loss=12.143, rho=1.0e+04\n",
      "2023-08-08 20:26:30,057 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 3] h=7.169e-04, loss=12.491, rho=1.0e+05\n",
      "2023-08-08 20:26:30,658 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 3] h=2.230e-04, loss=15.975, rho=1.0e+06\n",
      "2023-08-08 20:26:31,149 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 4] h=1.295e-04, loss=12.284, rho=1.0e+06\n",
      "2023-08-08 20:26:32,012 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 4] h=4.915e-05, loss=12.507, rho=1.0e+07\n",
      "2023-08-08 20:26:32,594 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 5] h=2.995e-05, loss=12.321, rho=1.0e+07\n",
      "2023-08-08 20:26:33,500 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 5] h=1.215e-05, loss=12.430, rho=1.0e+08\n",
      "2023-08-08 20:26:34,227 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 6] h=7.727e-06, loss=12.345, rho=1.0e+08\n",
      "2023-08-08 20:26:35,479 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 6] h=3.287e-06, loss=12.412, rho=1.0e+09\n",
      "2023-08-08 20:26:37,604 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 6] h=1.046e-06, loss=13.076, rho=1.0e+10\n",
      "2023-08-08 20:26:39,184 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 7] h=5.956e-07, loss=12.376, rho=1.0e+10\n",
      "2023-08-08 20:26:43,631 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 7] h=2.260e-07, loss=12.425, rho=1.0e+11\n",
      "2023-08-08 20:26:45,120 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 8] h=1.447e-07, loss=12.381, rho=1.0e+11\n",
      "2023-08-08 20:26:48,488 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 8] h=5.912e-08, loss=12.404, rho=1.0e+12\n",
      "2023-08-08 20:26:59,097 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 8] h=1.274e-08, loss=12.634, rho=1.0e+13\n",
      "2023-08-08 20:27:00,561 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 9] h=6.932e-09, loss=12.387, rho=1.0e+13\n",
      "2023-08-08 20:27:03,965 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:206] - INFO: [iter 9] h=2.493e-09, loss=12.395, rho=1.0e+14\n",
      "2023-08-08 20:27:03,966 - /home/zhangkeli/anaconda3/lib/python3.9/site-packages/castle/algorithms/gradient/notears/linear.py[line:222] - INFO: FINISHED\n"
     ]
    }
   ],
   "source": [
    "nt = Notears()\n",
    "nt.learn(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "625f3f2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "nt_estimated_graph = nt.causal_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8ef19a7b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x216 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<castle.common.plot_dag.GraphDAG at 0x7f1c72de2a00>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Plot estimated graph and true graph\n",
    "GraphDAG(nt_estimated_graph, true_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3798b431",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The performance for notears: \n",
      "{'fdr': 0.087, 'tpr': 0.1429, 'fpr': 0.0013, 'shd': 126, 'nnz': 23, 'precision': 0.913, 'recall': 0.1429, 'F1': 0.2471, 'gscore': 0.1293}\n"
     ]
    }
   ],
   "source": [
    "# Evaluation \n",
    "nt_metrics = MetricsDAG(nt_estimated_graph, true_graph)\n",
    "print(f\"The performance for notears: \\n{nt_metrics.metrics}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb160091",
   "metadata": {},
   "source": [
    "### 3.2 Setting 2:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2be814fb",
   "metadata": {},
   "source": [
    "  1. Data files: \"alarm.csv\" and 'causal_prior.csv'.\n",
    "  2. Use a time sliding window to generate IID samples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "85f0fb8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create the prior knowledge object for the PC algorithm \n",
    "prior_knowledge = PrioriKnowledge(causal_prior.shape[0])\n",
    "for i, j in zip(*np.where(causal_prior == 1)):\n",
    "    prior_knowledge.add_required_edge(i, j)\n",
    "\n",
    "for i, j in zip(*np.where(causal_prior == 0)):\n",
    "    prior_knowledge.add_forbidden_edge(i, j)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27f4bce1",
   "metadata": {},
   "source": [
    "#### Exemplified by the PC supporting prior knowledge injection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "aca0942f",
   "metadata": {},
   "outputs": [],
   "source": [
    "pc = PC(priori_knowledge=prior_knowledge)\n",
    "pc.learn(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "dc4cec1b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x216 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<castle.common.plot_dag.GraphDAG at 0x7f1c71309e50>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pc_estimated_graph = pc.causal_matrix\n",
    "# Plot estimated graph and true graph\n",
    "GraphDAG(pc_estimated_graph, true_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "1bdf6b66",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The performance for PC with Prior Knowledge: \n",
      "{'fdr': 0.3252, 'tpr': 0.7483, 'fpr': 0.0339, 'shd': 72, 'nnz': 163, 'precision': 0.6748, 'recall': 0.7483, 'F1': 0.7097, 'gscore': 0.3878}\n"
     ]
    }
   ],
   "source": [
    "# Evaluation \n",
    "pc_metrics = MetricsDAG(pc_estimated_graph, true_graph)\n",
    "print(f\"The performance for PC with Prior Knowledge: \\n{pc_metrics.metrics}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
